/**
 * Copyright 2012 Brigham Young University
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package edu.byu.nlp.cluster;

import java.util.logging.Logger;

import com.google.common.base.Preconditions;

/**
 * Clusterer that runs a base Clusterer multiple times, e.g., for random restarts.
 * 
 * @author rah67
 *
 */
public class MultipleRunClusterer implements ProbabilisticClusterer {

	private static Logger logger = Logger.getLogger(MultipleRunClusterer.class.getName());
	
	private final ProbabilisticClusterer baseClusterer;
	private final int numRestarts;
	
	public MultipleRunClusterer(ProbabilisticClusterer baseClusterer, int numRuns) {
		Preconditions.checkNotNull(baseClusterer);
		Preconditions.checkArgument(numRuns > 0);
		
		this.baseClusterer = baseClusterer;
		this.numRestarts = numRuns;
	}

	@Override
	public ProbabilisticClustering cluster(Dataset data, int numClusters) {
		logger.info("Starting run #1");
		ProbabilisticClustering bestClustering = baseClusterer.cluster(data, numClusters);
		
		for (int n = 1; n < numRestarts; n++) {
			logger.info("Starting run #" + n);

			// Do the clustering
			ProbabilisticClustering curClustering = baseClusterer.cluster(data, numClusters);
			logger.info(String.format("Objective value for restart %d = %f", n, curClustering.getObjectiveValue()));
			
			// If this is the best model so far, keep it!
			if (curClustering.getObjectiveValue() > bestClustering.getObjectiveValue()) {
				bestClustering = curClustering;
			}
		}
		logger.info("Maximal lower bound = " + bestClustering.getObjectiveValue());
		
		return bestClustering;
	}

}
